package com.tianji.promotion.lock;

import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.promotion.lock.strategy.LockStrategyEnum;
import com.tianji.promotion.lock.strategy.LockStrategyFactory;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Component
public class MyLockAspect {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private LockFactory lockFactory;

    @Autowired
    private LockStrategyFactory lockStrategyFactory;

    @Around("@annotation(lockAnno)")
    public Object lock(ProceedingJoinPoint pjp, MyLock lockAnno) throws Throwable {
        log.info(lockAnno.name());
        boolean locked = false;
        RLock lock = null;
        LockStrategyEnum lockStrategyEnum= null;
        // 获取锁对象
        try {
//            lockStrategy = lockStrategyFactory.getLockStrategy(lockAnno.lockStrategy());
//            locked = lockStrategy.lock(lockAnno);
            // 获取锁对象
            lock = lockFactory.getLock(lockAnno.lockType(), lockAnno.name());
            // 获取策略
            lockStrategyEnum = lockAnno.lockStrategy();
            // 执行策略
            locked = lockStrategyEnum.lock(lock, lockAnno);
            if (locked) {
                // 执行业务逻辑
                return pjp.proceed();
            }else{
                return null;
            }
//        RLock lock = lockFactory.getLock(lockAnno.lockType(), lockAnno.name());
//        boolean locked = false;
//        try{
//            // 尝试获取锁
//            locked = lock.tryLock(lockAnno.waitTime(), lockAnno.leaseTime(), lockAnno.timeUnit());
//            if(!locked){
//                // 有可能什么也不做，也有可能是抛异常
//                throw new BizIllegalException("操作太频繁");
//            }else{
//                // 执行业务逻辑
//                return pjp.proceed();
//            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BizIllegalException(500, e.getMessage(), e);
        } finally {
            // 释放锁
            if (locked) {
                lockStrategyEnum.unlock(lock);
            }
        }
    }
}

